// main.cpp

#include "gdal_priv.h"

#include <iostream>
#include <string>
#include <vector>
#include "getopt_pp.h"
#include "wGdalRaster.h"
#define WGDALRASTER_H_IMPLEMENTATION 1
#include "wGdalRaster.h"
#include "wstringutils.h"


using namespace std;
using namespace GetOpt;

bool isInChina(string geofilename) {
	string dsnamelon = string("HDF5:") + geofilename + "://Geolocation/Longitude" ;
	string dsnamelat = string("HDF5:") + geofilename + "://Geolocation/Latitude" ;
	wGdalRasterFloat raslon , raslat ;
	bool ok1 = raslon.open(dsnamelon) ;
	if( ok1==false ) {
		cout<<"error, failed to open lon at "<<dsnamelon<<endl ;
		return false ;
	}
	ok1 = raslat.open(dsnamelat) ;
	if( ok1==false ) {
		cout<<"error, failed to open lat at "<<dsnamelon<<endl ;
		return false ;
	}

	int llxsize = raslon.getXSize() ;
	int llysize = raslon.getYSize() ;
	int llasize = llxsize*llysize ;

	for(int iy = 10 ; iy < llysize; iy+=10 )
	{
		for(int ix = 10 ; ix < llxsize ; ix+=10 )
		{
			int ii = iy * llxsize+ix ;
			float lon1 = raslon.getValuef(ii,0) ;
			float lat1 = raslat.getValuef(ii,0) ;
			if( lon1>75.f && lon1< 135.f && lat1> 18.f && lat1< 52.f ) {
				return true ;
			}
		}
	}
	return false ;
}

bool isDaytime(string geofilename)
{
	/////// day or night
	GDALDataset* hdfds = (GDALDataset*)GDALOpen(geofilename.c_str(),GA_ReadOnly);
	if( hdfds==0 ){
		cout<<"bad hdf ds."<<endl ;
		return false ;
	}
	char ** SUBDATASETS = GDALGetMetadata( (GDALDatasetH)hdfds, "" );//在hdf根域查找
	bool isday=false;
    if( CSLCount(SUBDATASETS) > 0 )
    {
        for(int  i = 0; SUBDATASETS[i] != NULL; i++ )
        {
            string tmpstr=string(SUBDATASETS[i]);
            if( tmpstr.find("Day_Or_Night_Flag=") != std::string::npos ){
            	if( tmpstr.compare("Day_Or_Night_Flag=D") ==0 ){
            		isday=true ;//day
            	}else{
            		isday = false ;//not day
            	}
            	break ;
            }
        }
    }
    GDALClose(hdfds);
    return isday;
}



int main( int argc ,char* argv[] )
{
	cout<<"For every FY3D L1 GEO in china and in Daytime run the command."<<endl ;
	cout<<"version v1.0 2024/9/29"<<endl ;
	cout<<"usage: -r /some/L1/GEO1K/ -d ymd8 -c '/some/command -x {HHMM} -y {HHMM}...' "<<endl; 
	cout<<"-r     root dir of GEO1K."<<endl;
	cout<<"-d     date in YYYYMMDD format."<<endl ;
	cout<<"-c     command to run, {YYYY} {YYYYMMDD} {HHMM} will be replace."<<endl ;
	cout<<"---------"<<endl ;

	GDALAllRegister() ;

    string rootdir , date , command ;
    vector<float> extentll ;//in order leftlon rightlon bottomlat toplat

	GetOpt_pp ops(argc, argv);
	ops >> Option('r',rootdir)>> Option('d', date) >>Option('c', command) ;

	cout<<"rootdir: "<<rootdir<<endl;
	cout<<"date: "<<date<<endl;
	cout<<"command: "<<command<<endl;

	if( rootdir=="" ) {
		cout<<"Error , rootdir is empty."<<endl;
		return 11 ;
	}
	if( date=="" ) {
		cout<<"Error , date is empty."<<endl;
		return 11 ;
	}
	if( command=="" ) {
		cout<<"Error, command is empty."<<endl;
		return 11 ;
	}

	int hour0 = 3 ;
	int hour1 = 10 ;
	string yearstr = date.substr(0,4);
	int numok = 0 ;
	for(int ihour = hour0 ; ihour <= hour1 ; ++ ihour ) {

		for(int imm = 0 ; imm <= 55 ; imm+=5 ) {
			char hhmmbuff[16] ;
			sprintf( hhmmbuff, "%02d%02d" , ihour , imm ) ;
			string hhmmstr(hhmmbuff);
			string fullname = rootdir+ yearstr + "/" + date+ "/FY3D_MERSI_GBAL_L1_"+date+"_"+ hhmmstr +"_GEO1K_MS.HDF";
			bool isOk = isInChina(fullname) ;
			bool isday=isDaytime(fullname) ;
			cout<<"--- try " << fullname<<endl;
			if( isOk && isday ) {
				numok++;
				cout<<"cn and day, will run "<<endl;
				//{YYYY} {YYYYMMDD} {HHMM}
				string cmd1 = wStringUtils::replaceString(command,"{YYYY}", yearstr ) ;
				cmd1 = wStringUtils::replaceString(cmd1,"{YYYYMMDD}", date ) ;
				cmd1 = wStringUtils::replaceString(cmd1,"{HHMM}", hhmmstr ) ;
				cout<<"cmd: "<<cmd1<<endl;
				int ret = system( cmd1.c_str() ) ;
				cout<<"retcode: "<<ret<<endl;

			}else{
				cout<<"skip cn "<< isOk <<", day "<< isday <<endl;
			}
		}
	}
 	cout<<"all pass file count: "<<numok<<endl;
	cout<<"done"<<endl;
	return 0 ;
}


